/**
 * 
 */
package com.solome.core;

import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import com.badlogic.gdx.utils.ObjectMap.Entry;
import com.solome.base.Logger;
import com.solome.util.csv.CsvLoader;
import com.solome.util.csv.CsvParam;
import com.solome.util.csv.XlsKey;

/**
 * @author
 * 
 */
public abstract class ResourceModelImpl<T> extends Dictionary<T> implements
		ResourceModel<T> {

	protected String resFile;// 资源文件路径
	protected Class<T> _class;// 模板类
	protected CsvParam xlsKey;

	public ResourceModelImpl() {
	}

	/**
	 * 构造函数
	 * 
	 * @param resFile
	 *            配置文件路径
	 * @param _class
	 *            模板类定义
	 */
	public ResourceModelImpl(String resFile, Class<T> _class) {
		this.resFile = resFile;
		this._class = _class;

		Field[] arrayOfField = _class.getDeclaredFields();

		for (Field field : arrayOfField) {
			Annotation[] anos = field.getDeclaredAnnotations();
			for (Annotation annotation : anos) {
				CsvParam param = new CsvParam();
				param.setField(field);
				param.setName(field.getName());
				if (annotation instanceof XlsKey) {
					this.xlsKey = param;
				}
			}
		}
	}

	/**
	 * 将工厂内的资源打包成对象数组返回
	 * 
	 * @return 资源对象数组
	 */
	@Override
	public T[] asArray() {
		return asArray(xlsKey.getName());
	}

	/**
	 * 
	 * @param list
	 * @return
	 */
	@SuppressWarnings("unchecked")
	protected T[] asArray(String field) {
		List<T> list = this.sort(field);
		T[] valueArrays = (T[]) Array.newInstance(_class, list.size());
		for (int i = 0; i < list.size(); i++) {
			valueArrays[i] = list.get(i);
		}
		return valueArrays;
	}

	/**
	 * 获取资源对象
	 * 
	 * @param resID
	 *            资源不重复ID
	 * @return 资源对象
	 */
	@Override
	public T get(int resID) {
		return this.lookupEntry(resID);
	}

	/**
	 * 通过名称获取资源对象，有的工厂未实现
	 * 
	 * @param resName
	 *            资源名称
	 * @return 资源对象
	 */
	@Override
	public T get(String resName) {
		return this.lookupEntry(resName);
	}

	/**
	 * 获取关键值
	 * 
	 * @return
	 */
	protected int getKeyValue(T value) {
		if (xlsKey == null)
			return 0;
		return this.getValue(value, xlsKey.getField().getName());
	}

	/**
	 * 获取关键字名称
	 * 
	 * @param value
	 * @return
	 */
	protected String getName(T value) {
		try {
			Method method = _class.getMethod("getName");
			String name = (String) method.invoke(value);
			return name;
		} catch (Exception ex) {
			Logger.error("BuggerLogger", ex.getMessage());
			ex.printStackTrace();
		}
		return null;
	}

	/**
	 * 取得字段值
	 * 
	 * @param value
	 *            目标对象
	 * @param property
	 *            属性名称
	 * @return 值
	 */
	protected int getValue(T value, String property) {
		try {
			String methodName = property;
			methodName = methodName.substring(0, 1).toUpperCase()
					+ methodName.substring(1, methodName.length());
			methodName = "get" + methodName;
			Method method = _class.getMethod(methodName);
			Integer key = (Integer) method.invoke(value);
			return key;
		} catch (Exception ex) {
			Logger.error("BuggerLogger", ex.getMessage());
			ex.printStackTrace();
		}
		return 0;
	}

	public int length() {
		return this.countEntries();
	}

	/**
	 * 加载资源，默认加载方法
	 */
	@Override
	public void load() throws Exception {
		this.loadAll();
	}

	/**
	 * 
	 * @throws Exception
	 */
	public void loadAll() throws Exception {
		this.reset();
		CsvLoader<T> loader = new CsvLoader<T>();
		com.badlogic.gdx.utils.Array<String[]> sheet = loader
				.readCSVFile(resFile);
		com.badlogic.gdx.utils.Array<CsvParam> params = loader
				.loadFields(_class);
		loader.loadAll(sheet, params, _class);
		for (Entry<Integer, T> entry : loader) {
			T value = entry.value;
			Integer key = getKeyValue(value);
			String name = getName(value);
			if (name == null) {
				name = "" + key;
			}
			addEntry(key, name, value);
		}

		print();
	}

	/**
	 * 
	 * @throws Exception
	 */
	public void loadAllList() throws Exception {
		// this.reset();
		// CsvLoader<T> loader = new CsvLoader<T>(resFile, _class);
		// // loader.loadAsList(sheets);
		// Integer cursor = 0;
		//
		// for (T value : loader.loadAllList()) {
		// // T value = entry.getValue();
		// // Integer key = getKeyValue(value);
		// String name = getName(value);
		// if (name == null) {
		// name = "" + cursor;
		// }
		// addEntry(cursor, name, value);
		// cursor++;
		// }
		// print();
	}

	/**
	 * 
	 * @param sheets
	 * @throws Exception
	 */
	protected void loadList(String[] sheets) throws Exception {
		// this.reset();
		// CsvLoader<T> loader = new CsvLoader<T>(resFile, _class);
		// // loader.loadAsList(sheets);
		// Integer cursor = 0;
		// for (T value : loader.loadAsList(sheets)) {
		// // T value = entry.getValue();
		//
		// // Integer key = getKeyValue(value);
		// String name = getName(value);
		// if (name == null) {
		// name = "" + cursor;
		// }
		// addEntry(cursor, name, value);
		// cursor++;
		// }
		// print();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.cn.game.server.excel.model.ResourceModel#print()
	 */
	@Override
	public void print() {
		for (T value : iterate()) {
			System.err.println("加载[" + _class.getSimpleName() + "] " + value);
		}
	}

	/**
	 * 排序
	 */
	protected List<T> sort() {
		List<T> result = iterate();
		Collections.sort(result, new Comparator<T>() {
			@Override
			public int compare(T o1, T o2) {
				return getKeyValue(o1) < getKeyValue(o2) ? 0 : 1;
			}
		});
		return result;
	}

	/**
	 * 按某字段升序排列
	 * 
	 * @param field
	 * @return
	 */
	protected List<T> sort(final String field) {
		List<T> result = iterate();
		Collections.sort(result, new Comparator<T>() {
			@Override
			public int compare(T o1, T o2) {
				return getValue(o1, field) < getValue(o2, field) ? 0 : 1;
			}
		});
		return result;
	}

	/**
	 * 按某字段降序排列
	 * 
	 * @param field
	 * @return
	 */
	protected List<T> sortDESC(final String field) {
		List<T> result = iterate();
		Collections.sort(result, new Comparator<T>() {
			@Override
			public int compare(T o1, T o2) {
				return getValue(o1, field) < getValue(o2, field) ? 1 : 0;
			}
		});
		return result;
	}
}
